from flask_socketio import SocketIO, join_room, leave_room, emit
from flask import request, Flask
import uuid
from applications.utils.http import success_api, fail_api


class RoomManager:
    def __init__(self, app: Flask):
        """初始化房间管理器"""
        self.socketio = SocketIO(app, cors_allowed_origins="*", always_connect=True, logger=True, engineio_logger=True)
        self.rooms = {}  # 存储房间信息：{房间号: {用户ID: 连接ID}}
        self.namespace = '/ws'
        # 注册事件处理程序
        self._register_handlers()

    def _register_handlers(self):
        """注册 Socket.IO 事件处理程序"""

        @self.socketio.on('create_room', namespace=self.namespace)
        def handle_create_room():
            """创建房间（生成唯一通讯码）"""
            room_code = str(uuid.uuid4())[:8]  # 8位随机通讯码
            self.rooms[room_code] = {}
            return {'room_code': room_code}
            # return success_api(data={
            #     'room_code': room_code
            # })

        @self.socketio.on('join_room', namespace=self.namespace)
        def handle_join_room(data):
            """加入房间"""
            room_code = data['room_code']
            user_id = data['user_id']  # 前端生成的用户ID（如UUID）

            if room_code not in self.rooms:
                emit('message', {"event": 'room_error', "data": None, 'message': '房间不存在'})
                return

            # 记录用户与房间的关联
            self.rooms[room_code][user_id] = request.sid
            join_room(room_code, request.sid, self.namespace)

            # 通知房间内其他用户有新用户加入
            emit('message', {"event": "user_joined", "data": {
                'user_id': user_id, 'users': list(self.rooms[room_code].keys())
            }}, room=room_code, include_self=True)
            return {
                'users': list(self.rooms[room_code].keys())
            }

        @self.socketio.on('signal', namespace=self.namespace)
        def handle_signal(data):
            """转发信令消息（offer/answer/candidate）"""
            room_code = data['room_code']
            target_user = data['target_user']  # 目标用户ID
            signal_type = data['type']  # offer/answer/candidate
            signal_data = data['data']  # 信令内容

            if room_code not in self.rooms or target_user not in self.rooms[room_code]:
                emit("message", {"event": 'signal_error', data: None, 'message': '目标用户不在房间内'})
                return

            # 转发信令给目标用户
            target_sid = self.rooms[room_code][target_user]
            emit("message", {
                "event": 'signal',
                "data": {
                    'from_user': data['from_user'],
                    'type': signal_type,
                    'data': signal_data,
                    'room_code': room_code
                }
            }, to=target_sid)

        @self.socketio.on('disconnect', namespace=self.namespace)
        def handle_disconnect():
            """处理用户断开连接，清理房间信息"""
            for room_code, users in list(self.rooms.items()):
                for user_id, sid in list(users.items()):
                    if sid == request.sid:
                        del self.rooms[room_code][user_id]
                        leave_room(room_code, sid, self.namespace)
                        # 通知房间内其他用户该用户离开
                        emit("message", {'event': 'user_left',
                                         "data": {'user_id': user_id, 'users': list(self.rooms[room_code].keys())}},
                             room=room_code)
                        # 如果房间为空，删除房间
                        if not self.rooms[room_code]:
                            del self.rooms[room_code]
                        return
